package framework.webclient.google;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import com.sun.jersey.core.util.Base64;

import framework.webclient.ProxyData;


public class GoogleAuthentication {	
	private String gaeAppBaseUrl;
	private String gaeAppLoginUrl;
	private final String googleLoginUrl = "https://www.google.com/accounts/ClientLogin";
	private final String service = "ah";
	private Cookie authCookie;
	private ProxyData proxyData;

	//Constructor creates the cookie
	public GoogleAuthentication(String gaeAppBaseUrl, String googleAccount, String googlePassword)
	{
		initialize(gaeAppBaseUrl, googleAccount, googlePassword);
	}
	
	public GoogleAuthentication(String gaeAppBaseUrl, String googleAccount, String googlePassword, ProxyData proxy)
	{
		this.proxyData = proxy;
		initialize(gaeAppBaseUrl, googleAccount, googlePassword);
	}
	
	private void initialize(String gaeAppBaseUrl, String googleAccount,
			String googlePassword) {
		this.gaeAppBaseUrl = gaeAppBaseUrl;
		this.gaeAppLoginUrl = gaeAppBaseUrl + "_ah/login";
		try {
			String authToken = getToken(googleAccount,googlePassword);
			authCookie = getAuthCookie(authToken);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public Cookie getAuthCookie() {
		return authCookie;
	}

	public void setAuthCookie(Cookie authCookie) {
		this.authCookie = authCookie;
	}
	
	public void setProxy(String host, Integer port, String pcname, String domain, String proxyusername, String proxypassword) {
		this.proxyData.proxyserver = host;
		this.proxyData.proxyport = port;
		this.proxyData.pcname = pcname;
		this.proxyData.domain = domain;
		this.proxyData.proxyusername = proxyusername;
		this.proxyData.proxypassword = proxypassword;
	}
	
	private String getToken(String googleAccount, String googlePassword) throws MalformedURLException, ProtocolException, UnsupportedEncodingException, IOException	{
		String token = null;
		HttpURLConnection h = getConnection(googleAccount,googlePassword);
		token= extractAuthTokenFromResponse(h);
		return token;
	}
	
	private Cookie getAuthCookie(String authToken) throws ClientProtocolException, IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		
		
//		Credentials credentials = new UsernamePasswordCredentials(username, password); 
//		AuthScope scope = new AuthScope(HTTP_PROXY_NOC_ANRITSU_CO_JP, _8080); 
//		httpClient.getCredentialsProvider().setCredentials(scope, credentials); 
	
		if (proxyEnabled()) {
			// NTLM
			HttpHost proxy = new HttpHost(proxyData.proxyserver, proxyData.proxyport, "http");  
			httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 
			NTCredentials creds = new NTCredentials(proxyData.proxyusername, proxyData.proxypassword, proxyData.pcname, proxyData.domain);
			httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
		}
		
		Cookie retObj = null;
		String cookieUrl = gaeAppLoginUrl + "?continue=" 
				+ URLEncoder.encode(gaeAppBaseUrl,"UTF-8") + "&auth=" + URLEncoder.encode 
				(authToken,"UTF-8"); 
		HttpGet httpget = new HttpGet(cookieUrl);
		HttpResponse response = httpClient.execute(httpget);
		if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK ||
			response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_NO_CONTENT) {
			
			if (httpClient.getCookieStore().getCookies().size() > 0) {
				retObj= httpClient.getCookieStore().getCookies().get(0);
			}
		
		}
		return retObj;
	
	}
	
	private boolean proxyEnabled() {
		return this.proxyData != null;
	}

	private HttpURLConnection getConnection(String username, String password)
	throws MalformedURLException, IOException, ProtocolException,
		UnsupportedEncodingException {
			
		HttpURLConnection urlConnection;
		URL url = new URL(googleLoginUrl);
		urlConnection = (HttpURLConnection) url.openConnection();
		urlConnection.setRequestMethod("POST");
		urlConnection.setDoInput(true);
		urlConnection.setDoOutput(true);
		urlConnection.setUseCaches(false);
		urlConnection.setRequestProperty("Content-Type",
		"application/x-www-form-urlencoded");
		
		if (proxyEnabled()) {
		     //proxy user and pass
			System.setProperty("proxySet", "true");
			System.setProperty("proxyHost", proxyData.proxyserver);
			System.setProperty("proxyPort", proxyData.proxyport.toString());
			urlConnection.setRequestProperty(
	            "Proxy-Authorization", 
	            "Basic " + Base64.encode(
	                (username + ":" + password).getBytes()
	            )
	        );
		}
        
		StringBuilder content = new StringBuilder();
		content.append("Email=").append(username);
		content.append("&Passwd=").append(password);
		content.append("&service=").append(service);
		
		OutputStream outputStream = urlConnection.getOutputStream();
		outputStream.write(content.toString().getBytes("UTF-8"));
		outputStream.close();
		return urlConnection;
	}
	
	private String extractAuthTokenFromResponse(HttpURLConnection urlConnection)
	throws IOException {
		int responseCode = urlConnection.getResponseCode();
		System.out.println(responseCode);
		StringBuffer resp = new StringBuffer(); 
		if (responseCode == HttpURLConnection.HTTP_OK) {
			InputStream inputStream = urlConnection.getInputStream();
			BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
			String line; 
			
			while ((line = rd.readLine()) != null) { 	
				if(line.startsWith("Auth=")) {
					resp.append(line.substring(5)); 
				}
			} 
			rd.close(); 		
		}
		return resp.toString();
	}
}



